/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.loli.hernandez.modelo;

import com.loli.hernandez.modelo.beans.Database;
import com.loli.hernandez.modelo.beans.DatabaseTable;
import com.loli.hernandez.modelo.beans.TableColumn;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

/**
 *
 * @author Néstor Hernández Loli
 * @since 14/04/2011
 * Representa la principal clase DAO que administrará el acceso al servidor de 
*base de datos
 * La vista esta ubicada en el paquete presentación
 */
public class DataManager {

    private final String server, user, password, port, driver;
    private boolean driverLoaded = false;
    //private String databaseName = "";
    //se carga una base de datos vacía
    private Database database = new Database("");
   

    /**
     * 
     * @param server El nombre del servidor de BD a conectarse
     * @param port El número del puerto usado para conexión
     * @param user El nombre del usuario
     * @param password La contraseña requerida para acceso
     */
    public DataManager(String server, String port, String user, String password) {
        this.server = server;
        this.user = user;
        this.password = password;
        this.port = port;
        // this.databaseName = databaseName;
        this.driver = "com.mysql.jdbc.Driver"; //Driver de MySQL
    }

    /**
     * 
     * @param database La base de datos seleccionada para conectarse
     * y poder navegar entre sus tablas
     */
    public void setDatabase(Database database) {
        this.database = database;
    }

    /**
     * 
     * @return El objeto base de datos 
     */
    public Database getDatabase() {
        return database;
    }

    /**
     * 
     * @return La URL la dirección JDBC usada para conectarse al servidor de 
     * base de datos
     */
    public String getUrlConnection() {
        return "jdbc:mysql://" + server + ":" + port + "/" + database.getDatabaseName();
    }

    public String getDriver() {
        return driver;
    }

    public String getUser() {
        return user;
    }

    public String getPassword() {
        return password;
    }

    /*
     * Estos métodos no deberían ser usados para el objetivo de este programa
     * por lo tanto están definidos como privados o protegidos
     */
    /**
     * Permite inicializar la clase del driver usado para la conexión a base de 
     * datos
     * @throws ClassNotFoundException en caso el driver no esté disponible
     */
    private void initializeDriver() throws ClassNotFoundException {
        Class.forName(driver);
        driverLoaded = true;
    }

    /**
     * 
     * @return Un objeto <tt>Connection</tt> representando la conexión a base de
     * datos
     * @throws SQLException en caso ocurra un error en la conexión
     */
    protected Connection getDatabaseConnection() throws SQLException {
        if (!driverLoaded) {
            try {
                initializeDriver();
            } catch (ClassNotFoundException e) {
                System.out.println("" + e.getMessage());
                return null;
            }
        }
        return DriverManager.getConnection(getUrlConnection(), user, password);
    }

    /**
     * Permite crear un nuevo objeto Statement 
     * @return Un objeto <tt>Statement</tt> inicializado usado para realizar operaciones
     * en la base de datos
     * @throws SQLException en caso ocurra un error creando el objeto
     */
    protected Statement createNewStatement() throws SQLException {
        Connection cn = getDatabaseConnection();
        Statement stmt = cn.createStatement();
        return stmt;
    }

    /**
     * 
     * @param sql Una consulta SQL sencilla
     * @return Un objeto inicializado <tt>ResultSet</tt> que permite recorrer
     * un conjunto de datos resultado de la consulta SQL
     * @throws SQLException 
     */
    protected ResultSet getResultSetFromQuery(String sql) throws SQLException {
        Connection cn = getDatabaseConnection();
        Statement stmt = cn.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        return rs;
    }

    /**
     * Este método permite cerrar de forma completa la conexión a BD, empieza
     * por cerrar los objetos Statement y luego el objeto Connection
     * @param stmt El objeto <tt>Statement</tt> por el que se cerrará la conexión
     * @throws SQLException 
     */
    protected void fullDisposeStatement(Statement stmt) throws SQLException {
        Connection cn = stmt.getConnection();
        stmt.close();
        stmt = null;
        cn.close();
        cn = null;
    }

    /**
     * Este método permite cerrar de forma completa la conexión a BD, empieza
     * por cerrar los objetos ResultSet, Statement y por último el objeto 
     * Connection
     * @param rs El objeto <tt>ResultSet</tt> por el que se cerrará la conexión
     * @throws SQLException 
     */
    protected void fullDisposeResultSet(ResultSet rs) throws SQLException {
        Statement stmt = rs.getStatement();
        Connection cn = stmt.getConnection();
        rs.close();
        rs = null;
        stmt.close();
        stmt = null;
        cn.close();
        cn = null;
    }

    /**
     * Permite mostrar las bases de datos existentes en el servidor 
     * @return un listado de base de datos
     * @throws SQLException 
     */
    public ArrayList<Database> showAllDatabases()
            throws SQLException {
        return DatabasePeer.showAllDatabases(this);
    }

    /**
     * Permite retornar un listado de tablas de una base de datos
     * se requiere usar el método setDatabase(..) de esta clase
     * @return un listado de tablas 
     * @throws SQLException 
     */
    public ArrayList<DatabaseTable> getTablesFromDatabase() throws SQLException {
        return DatabaseTablePeer.getTablesFromDatabase(this, this.database);
    }

    /**
     * 
     * @param table  un objeto <tt></tt>
     * @return
     * @throws SQLException 
     */
    public ArrayList<TableColumn> getColumnsFromTable(DatabaseTable table)
            throws SQLException {
        return TableColumnPeer.getColumnsFromTable(this, table);
    }
}
